package com.google.gson.internal; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.lang.reflect.Field; import java.lang.reflect.Method; public abstract class UnsafeAllocator { public abstract <T> T newInstance(Class<T> paramClass) throws Exception; public static UnsafeAllocator create() { try { Class unsafeClass = Class.forName("sun.misc.Unsafe"); Field f = unsafeClass.getDeclaredField("theUnsafe"); f.setAccessible(true); final Object unsafe = f.get(null); Method allocateInstance = unsafeClass.getMethod("allocateInstance", new Class[] { Class.class }); return new UnsafeAllocator() { public <T> T newInstance(Class<T> c) throws Exception { return this.val$allocateInstance.invoke(unsafe, new Object[] { c }); } }; } catch (Exception ignored) { try { Method newInstance = ObjectInputStream.class.getDeclaredMethod("newInstance", new Class[] { Class.class, Class.class }); newInstance.setAccessible(true); return new UnsafeAllocator() { public <T> T newInstance(Class<T> c) throws Exception { return this.val$newInstance.invoke(null, new Object[] { c, Object.class }); } }; } catch (Exception ignored) { try { Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod("getConstructorId", new Class[] { Class.class }); getConstructorId.setAccessible(true); final int constructorId = ((Integer)getConstructorId.invoke(null, new Object[] { Object.class })).intValue(); Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance", new Class[] { Class.class, Integer.TYPE }); newInstance.setAccessible(true); return new UnsafeAllocator() { public <T> T newInstance(Class<T> c) throws Exception { return this.val$newInstance.invoke(null, new Object[] { c, Integer.valueOf(constructorId) }); } } ; } catch (Exception ignored) { } } } return new UnsafeAllocator() { public <T> T newInstance(Class<T> c) { throw new UnsupportedOperationException("Cannot allocate " + c); } }; } }